package com.star.basedemo.log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;


/**
 * logAop
 */
@Aspect // 声明是一个切面
@Component //该标签把LoggerAspect类放到IOC容器中
public class LogAop {

    @Autowired
    HttpServletRequest request; //这里可以获取到request

    @Pointcut("@annotation(com.star.basedemo.log.Oplog)")
    public void Pointcut() {
    }

    /**
     * 实际我们通过 joinPoint 就可以拿到 其他参数的值 不过这里详细
     *
     * @param joinPoint 切点
     * @param result    返回值
     *                  后置通知
     */
    @AfterReturning(value = "Pointcut()", returning = "result")
    public void afterReturnMethod(JoinPoint joinPoint, Object result) {

        // 获取请求url
        String url = request.getRequestURI().toString();
        // 获取请求ip
        String ip = request.getRemoteAddr();
        // 获取方法参数
        Object[] pointCut = joinPoint.getArgs();
        // 从 request 中获取请求参数
        request.getParameterMap().forEach((k, v) -> System.out.println("k: " + k + "\tv: " + Arrays.toString(v)));
        System.out.println("ip："+ip);
        System.out.println("请求url："+url);
        for (Object o : pointCut) {
            System.out.println("方法参数:" + o);
        }
        // 获取 方法 对应的 类Class
        Class<?> aClass = joinPoint.getTarget().getClass();

        // 执行方法的类名 com.star.service.studentService
        String aClassName = aClass.getName();

        // 执行方法的方法名
        String methodName = joinPoint.getSignature().getName();

        // 获取注解信息
        String value = "";
        String actionType = "";

        //1.获取所有的公共方法
        Method[] methods = aClass.getMethods();
        //2.对这些公共方法进行遍历
        for (Method method : methods) {
            if (method.getName().equals(methodName)) { // 比对方法名是否相同
                // 比对参数是否一致
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == pointCut.length) {
                    value = method.getAnnotation(Oplog.class).value();
                    actionType = method.getAnnotation(Oplog.class).actionType();
                    break;
                }
            }
        }
        System.out.println("注解方法返回值:" + result);
        System.out.println("注解类路径" + aClassName);
        System.out.println("注解方法:" + methodName);
        System.out.println("注解Value值:" + value);
        System.out.println("注解actionType值:" + actionType);
    }
}

